package com.ace.user.module.service.impl;

import com.ace.user.common.bean.dto.TokenDTO;
import com.ace.user.common.bean.dto.UserDTO;
import com.ace.user.exception.BusinessException;
import com.ace.user.mqtt.SendMessage;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ace.user.common.bean.RequestDTO;
import com.ace.user.common.constant.C;
import com.ace.user.common.http.FeignTokenService;
import com.ace.user.config.locale.RLocale;
import com.ace.user.module.entity.User;
import com.ace.user.module.entity.UserInfo;
import com.ace.user.module.mapper.UserUserInfoMapper;
import com.ace.user.module.mapper.UserUserMapper;
import com.ace.user.module.service.IUserService;
import com.ace.user.module.service.WatchDogService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import javax.annotation.Resource;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * 用户定义表 服务实现类
 * </p>
 *
 * @author jobObj
 * @since 2019-10-11
 */
@Service
@Transactional(rollbackFor = Exception.class, propagation = Propagation.SUPPORTS)
@Slf4j
public class UserServiceImpl extends ServiceImpl<UserUserMapper, User> implements IUserService {

    @Autowired
    private RLocale rLocale;
    @Resource
    private UserUserInfoMapper userInfoMapper;

    @Resource
    private UserUserMapper userMapper;

    private WatchDogService watchDogService;

    @Value("hasp_default_user_count")
    private String defaultUserCount;

    @Resource
    private FeignTokenService feignTokenService;

    @Lazy
    @Autowired
    private SendMessage sendMessage;

    @Override
    @Transactional(propagation = Propagation.REQUIRED)
    public Integer add(UserDTO userDTO) {
        log.info("logout appId:{}  name:{} fullName:{}  password:{}", userDTO.getAppId(), userDTO.getName(), userDTO.getFullName(), userDTO.getPassword());
        /*if (!checkUserCount(userDTO.getAppId())) {
            throw new BusinessException(rLocale.getDTO("USER_ERR_REGISTER", C.U_30),rLocale.getMessage("USER_ERR_REGISTER_EXPEND1"));
        }*/
        // 查询同appId下是否有重复用户
        Integer userCount = userMapper.selectCount(new QueryWrapper<User>().eq(User.DB_APP_ID, userDTO.getAppId()).eq(User.DB_NAME, userDTO.getName()));
        if (userCount != null && userCount > 0) {
            throw new BusinessException(rLocale.getDTO("USER_ERR_REGISTER", C.U_30), rLocale.getMessage("USER_ERR_REGISTER_EXPEND2"));
        }
        User user = new User();
        BeanUtils.copyProperties(userDTO, user);
//        String id = IdUtil.getUserId();
//        user.setId(id);
        this.save(user);
        UserInfo userInfo = new UserInfo();
        userInfo.setId(user.getId());
        userInfoMapper.insert(userInfo);
        log.info("register result id:{}", user.getId());
        return user.getId();
    }


    @Override
    public Map<String, Object> login(RequestDTO<UserDTO> requestDTO) {
        UserDTO userDTO = requestDTO.getData();
        log.info("login name:{}  password:{}  appId:{}  type:{}", userDTO.getName(), userDTO.getPassword(), userDTO.getAppId(), userDTO.getType());
        Map<String, Object> userMap = this.baseMapper.selectUser(userDTO.getAppId(), userDTO.getName());
        //检查用户名是否正确
        if (userMap == null) {
            throw new BusinessException(rLocale.getDTO("USER_ERR_LOGIN", C.U_20), rLocale.getMessage("USER_ERR_LOGIN_EXPEND1"));
        }
        if (userMap.get("deleteFlag") != null) {
            if (Integer.parseInt(userMap.get("deleteFlag").toString()) == 1) {
                throw new BusinessException(rLocale.getDTO("USER_ERR_LOGIN", C.U_20), rLocale.getMessage("USER_ERR_LOGIN_EXPEND5"));
            }
        }
        if (!userMap.get("password").toString().equals(requestDTO.getData().getPassword())) {
            throw new BusinessException(rLocale.getDTO("USER_ERR_LOGIN", C.U_20), rLocale.getMessage("USER_ERR_LOGIN_EXPEND6"));
        }
        RequestDTO<TokenDTO> paramDTO = new RequestDTO<>();
        paramDTO.setVersion(requestDTO.getVersion());
        paramDTO.setType(requestDTO.getType());
        paramDTO.setUid(requestDTO.getUid());
        TokenDTO tokenDTO = new TokenDTO();
        tokenDTO.setUserId(userMap.get("id").toString());
        tokenDTO.setType(userDTO.getType());
        paramDTO.setData(tokenDTO);
        try {
            feignTokenService.deleteTokenByUserId(paramDTO);
        } catch (Exception e) {
            log.warn(e.getMessage());
            throw new BusinessException(rLocale.getDTO("USER_ERR_LOGIN", C.U_21), rLocale.getMessage("USER_ERR_LOGIN_EXPEND9"));
        }
        //给当前用户创建新的token
        JSONObject tokenObj = null;
        try {
            tokenObj = feignTokenService.addToken(paramDTO);
        } catch (Exception e) {
            log.warn(e.getMessage());
            throw new BusinessException(rLocale.getDTO("USER_ERR_LOGIN", C.U_21), rLocale.getMessage("USER_ERR_LOGIN_EXPEND9"));
        }
        userMap.put("token", tokenObj.getJSONObject("data").getJSONArray("list").getJSONObject(0).get("value"));
        UserInfo userInfo = userInfoMapper.selectOne(new QueryWrapper<UserInfo>().eq(UserInfo.DB_ID, Integer.valueOf(userMap.get("id").toString())));
        if (userInfo.getTokenStatus() != null) {
            if (userInfo.getTokenStatus() == 1) {
                Map<String, Object> messageMap = new HashMap<>();
                messageMap.put("command", C.OFFLINE);
                messageMap.put("userId", userInfo.getId());
                messageMap.put("connectNumber", userInfo.getConnectNum());
                messageMap.put("type", userInfo.getType());
                messageMap.put("offlineType", 1);//互踢为1
                if (!StringUtils.isEmpty(userMap.get("appId"))) {
                    messageMap.put("arise-topic", userMap.get("appId").toString() + "-server");
                    sendMessage.send(JSON.toJSONString(messageMap), userMap.get("appId").toString() + "-server");
                }
            }
        }
        userInfo.setId(Integer.valueOf(userMap.get("id").toString()));
        userInfo.setType(userDTO.getType().equals("web") ? 1 : 2);
        userInfo.setTokenStatus(C.N_1);
        userInfoMapper.updateById(userInfo);
        userMap.remove("password");
        userMap.remove("deleteFlag");
        log.info("method:{} result:{}", "login", userMap);
        return userMap;
    }

    @Override
    public void logout(RequestDTO<UserDTO> requestDTO) {
        UserDTO userDTO = requestDTO.getData();
        Map<String, Object> userMap = this.getMap(new QueryWrapper<User>().eq(User.DB_ID, userDTO.getId()));
        //检查用户是否存在
        if (userMap == null) {
            throw new BusinessException(rLocale.getDTO("USER_ERR_LOGIN", C.U_20), rLocale.getMessage("USER_ERR_LOGIN_EXPEND1"));
        }
        UserInfo userInfo = new UserInfo();
        userInfo.setId(userDTO.getId());
        userInfo.setTokenStatus(C.N_0);
        userInfoMapper.updateById(userInfo);
        //删除该用户下所有token
        RequestDTO<TokenDTO> paramDTO = new RequestDTO<>();
        paramDTO.setVersion(requestDTO.getVersion());
        paramDTO.setType(requestDTO.getType());
        TokenDTO tokenDTO = new TokenDTO();
        tokenDTO.setUserId(userDTO.getId().toString());
        paramDTO.setData(tokenDTO);
        try {
            feignTokenService.deleteTokenByUserId(paramDTO);
        } catch (Exception e) {
            log.debug(e.getMessage());
            throw new BusinessException(rLocale.getDTO("USER_ERR_LOGOUT", C.U_21), rLocale.getMessage("USER_ERR_LOGOUT_EXPEND2"));
        }
        log.info("method:{} result:{}", "logout", true);
    }

    @Override
    public boolean delUser(UserDTO userDTO) {
        User user = new User();
        user.setDeleteFlag(-1);
        boolean ret = this.update(user, new UpdateWrapper<User>().eq(User.DB_ID, userDTO.getId()).eq(User.DB_APP_ID, userDTO.getAppId()));
        log.info("delUser ret:{}  appId:{}  userId:{}", ret, userDTO.getAppId(), userDTO.getId());
        return ret;
    }

    @Override
    public List<Map<String, Object>> onLineUser(String appId, String userId) {
        List<Map<String, Object>> onLineUserList = this.userMapper.selectWebByAppId(appId, userId);
        onLineUserList.addAll(userMapper.selectAppByAppId(appId, userId));
        return onLineUserList;
    }

    public boolean checkUserCount(String appId) {
        boolean flag = false;
        int userCount = watchDogService.decryptFile().getJSONObject("userTotal").getIntValue(appId);
        if (userCount == 0) {
            userCount = Integer.parseInt(defaultUserCount);
        }
        // 查询appId下所有有效用户数
        int existUserCount = userInfoMapper.selectUserCountByAppId(appId);
        if (existUserCount < userCount) {
            flag = true;
        }
        return flag;
    }
}
